local japi = require 'jass.japi'
local parser = require 'types.record.parser'

if not japi['EXGetPlayerRealName'] then 
    print("缺少11运行环境")
    return 
end 

local export = {}

export.type = '11'

export.infomation = parser.new({
    "map_level:i4",
    "map_exp:i4",
    "played_games:i4",
},{
    map_level = 1,
    map_exp = 0,
    played_games = 0,
})

function export.is_sync(callback)
	if not export.current_player:is_online() then
        for i = 1, 12 do
            if ac.player(i):is_online() then
                export.current_player = ac.player(i)
                break
            end
        end
    end 
    export.current_player:is_self()
end

-- 获取模式配置
function export.get_match_type()
    return 0
end 

-- 获取地图配置项
function  export.get_map_config(name)
    return japi.GetStoredString(export.server_game_cache, "config", name) or "" 
end

-- 获取游戏开始时间
function export.get_game_starttime()
    if not export.game_starttime then 
        local year, month, day, hour, min, sec = japi.EXNetGetTime():match('(%d+)%-(%d+)%-(%d+)%s-(%d+)%:(%d+)%:(%d+)')
        export.game_starttime = os.time{
            year  = tonumber(year) or 2023, 
            month = tonumber(month) or 1, 
            day   = tonumber(day) or 1,
            hour  = tonumber(hour) or 0, 
            min   = tonumber(min) or 0, 
            sec   = tonumber(sec) or 0,
        }
    end
    return export.game_starttime
end

local mt = ac.player.__index

function mt:letter()
    return string.char(0x40 + self:get_id())
end

-- 获取积分
function mt:get_score(name)
    if not self.rpg_scores[name] then 
        if self:is_online() then 
            self.rpg_scores[name] = japi.GetStoredInteger(export.scores_game_cache, self:letter(), name) or 0
            print(('获取RPG积分:[%s][%s] = [%s]'):format(self:get_name(), name, self.rpg_scores[name]))
        else
            self.rpg_scores[name] = 0
        end
    end 
    return self.rpg_scores[name]
end

-- 获取公会名
function mt:get_guild_name()
    return self.server_guild_name or ""
end 

-- 获取公会职务
function mt:get_guild_role()
    if self.server_guild_role == 30 then 
        return "会长"
    elseif self.server_guild_role == 20 then
        return "管理员"
    end 
    return "成员"
end 

function mt:get_game_count()
    return self.played_games
end 

function mt:get_map_level()
    return self.map_level
end 

-- 获取地图等级排行
function mt:get_map_level_rank()
    return 0
end 

-- 是地图作者
function mt:is_author()
    return self.server_author == true
end

-- 是会员
-- 平台会员 100000
-- RPG会员 100001
-- 大冒险会员 200001
function mt:is_vip()
    return self.server_vip == true
end 

-- 保存积分
function mt:set_score(name, value)
    assert(math.type(value) == 'integer', "积分只能保存 “整数” ")
    self.rpg_scores[name] = value 
    if self:is_online() then 
        local letter = self:letter() .. "="
        japi.StoreInteger(export.scores_game_cache, letter, name, value)
        if export.is_sync() then 
            japi.SyncStoredInteger(export.scores_game_cache, letter, name)
        end
        print(('设置RPG积分:[%s][%s] = [%s]'):format(self:get_name(), name, value))
    end
end

-- 累加积分 (是否是通行证)
function mt:add_score(name, value, is_pc)
    assert(math.type(value) == 'integer', "积分只能保存 “整数” ")
    if not is_pc then 
        self:set_score(name, self:get_score(name) + value)
    else 
        self.rpg_scores[name] = self:get_score(name) + value
        if self:is_online() then 
            local letter = self:letter() .. "+"
            japi.StoreInteger(export.scores_game_cache, letter, name, value)
            if export.is_sync() then 
                japi.SyncStoredInteger(export.scores_game_cache, letter, name)
            end
            print(('增加RPG积分:[%s][%s] = [%s]'):format(self:get_name(), name, value))
        end
    end 
end 

-- 设置房间显示
-- 11平台已经干掉这种用法了 日
-- 平台代码 n="称号";d="初入江湖";s="";k=_G[n];if(k and k>0)then;for i=1,k do;for v in (tostring(_G[n..i]):sub(2)):gmatch("%d%d%d")do;s=s..v:char();end;end;return s;else return d;end;
function mt:set_stat(name, value)
    if self:is_online() then 
        -- local v = 0
        -- local i = 0
        -- local k = 0
        -- local j = ''
        -- local c = ''
        -- while true do
        --     i = i + 1 
        --     c = c .. ('%03d'):format((value):byte(i))
        --     local m = (((i-1)%2)+1)
        --     if m==2 then
        --         k = k + 1
        --         j = ("%s%d"):format(name,k)
        --         self:set_score(j, (tonumber('1'..c)))
        --         c = ""
        --     end 
        --     if i == #value then 
        --         if m<2 then 
        --             self:set_score(j, (tonumber(('1%06d'):format(tonumber(c)))))
        --         end
        --         self:set_score(name, k)
        --         break 
        --     end
        -- end 
        -- print(('设置房间显示:[%s][%s] = [%s]'):format(self:get_name(), name, value))
    end
end

-- 获取11真实名字
function mt:get_user_name()
    return japi.EXGetPlayerRealName(self.handle)
end

-- 保存存档
function mt:save_server(name, value)
    assert(type(value) == 'string', "存档只能保存 “字符串” ")
    assert(#(value) <= 64, "存档长度超过上限")
	if self.rpg_servers[name] == value then 
        return 
    end 
    self.rpg_servers[name] = value 
    if self:is_online() then 
        print(('11设置RPG存档:[%s][%s] = [%s]'):format(self:get_name(), name, value))
        japi.EXNetSaveRemoteData(self:get_id()-1, name, value)
    end 
end 
	
-- 读取存档
function mt:load_server(name)
	if not self.rpg_servers[name] then 
        if self:is_online() then 
            self.rpg_servers[name] = japi.GetStoredString(export.server_game_cache, japi.EXGetPlayerRealName(self.handle), name) or ""
        else 
            self.rpg_servers[name] = ""
        end 
	end 
	return self.rpg_servers[name]
end 

-- 获取玩家次数类道具剩余次数
function mt:get_item_count(name)
    if not self.rpg_items[name] then
        if self:is_online() then 
	        self.rpg_items[name] = japi.GetStoredInteger(self.billing_game_cache, "道具", name) or 0
        else 
	        self.rpg_items[name] = 0
        end 
    end 
    return self.rpg_items[name]
end

-- 消耗次数性道具 TODO 未验证
function mt:use_item(name, amount)
    name = tostring( name )
    amount = amount or 1
	if self:get_item_count(name) >= amount then 
        self.rpg_items[name] = self.rpg_items[name] - amount
        ac.wait(0, function ()
            japi.EXNetUseItem(self.handle, name, amount)
        end)
	end 
end 

-- 玩家是否拥有状态(时间类 道具)
function mt:has_status(name)
    if not self.rpg_status[name] then
        if self:is_online() then 
	        self.rpg_status[name] = japi.HaveStoredInteger(self.billing_game_cache, "状态", name) and 1 or 0
        else 
	        self.rpg_status[name] = 0
        end 
    end 
    return self.rpg_status[name] == 1
end

-- 玩家是否拥有道具(次数类 道具)
function mt:has_item(name)
	return self:get_item_count(name) > 0
end

function export.update()
    for i=1,12 do 
        local p = ac.player(i)
        if p:is_online() then 
            local t = p.infomation
            local l = t.map_level
            t.map_exp = t.map_exp + 1
            t.map_level = math.floor( ( t.map_exp // 60 ) ^ 0.5 ) + 1
            if p.played_games == t.played_games then 
                t.played_games = t.played_games + 1
                p:set_score("count", t.played_games)
            end
            p:set_score("exp", t.map_exp)
            p:set_score("lv", t.map_level)
            p:save_server("meta", export.infomation:encode(t))
        end 
    end 
end 

function export.init()

    export.server_game_cache = japi.InitGameCache "11.s"
    export.scores_game_cache = japi.InitGameCache "11.x"
    -- export.rank_game_cache = japi.InitGameCache "11.rank"
    export.current_player = ac.player(1)

    for i=1,12 do 
        local p = ac.player(i)
        p.billing_game_cache = japi.InitGameCache("11billing@" .. p:letter())
        p.rpg_scores = {}   
        p.rpg_servers = {}
        p.rpg_items = {}
        p.rpg_status = {}
        p.infomation = export.infomation:decode(p:load_server("meta"))
        p.map_level = math.floor( ( p.infomation.map_exp // 60 ) ^ 0.5 ) + 1
        p.played_games = p.infomation.played_games
    end 

    ac.loop(60 * 1000, function()
        export.update()
    end)
    
end

return export